#pragma once
#include "core_headers.hpp"

class EventLoop;
using EventCallback = std::function<void()>;
class Channel
{
public:
	Channel(EventLoop *loop, int fd)
		: _loop(loop), _fd(fd), _event(0), _revent(0)
	{
	}
	int Fd()
	{
		return _fd;
	}
	uint32_t Events()
	{
		return _event; // 获取想要监控的事件
	}
	void SetRevent(uint32_t events)
	{
		_revent = events; // 设置实际就绪的事件
	}
	// 描述符是否可写
	bool Writeable()
	{
		return _event & EPOLLOUT; // 都是1 才是1
	}
	// 描述符是否可读
	bool Readable()
	{
		return _event & EPOLLIN;
	}
	// 开启可读事件
	void EnableReadableEvent()
	{
		_event |= EPOLLIN; // 只要为1，就为1
						   // 后续会添加到eventloop中
		Update();
	}
	// 开启可写事件
	void EnableWriteableEvent()
	{
		_event |= EPOLLOUT;
		// 后续会添加到eventloop中
		Update();
	}
	// 解除可读事件监控
	void CloseReadableEvent()
	{
		_event &= ~EPOLLIN;
		// 后续会添加到eventloop中
		Update();
	}
	// 解除可写事件监控
	void CloseWriteableEvent()
	{
		_event &= ~EPOLLOUT;
		// 后续会添加到eventloop中
		Update();
	}
	// 解除所有事件监控
	void CloseAllEvent()
	{
		_event = 0;
		// 后续会添加到eventloop中
		Update();
	}
	// 移除监控
	void Remove();
	void Update();
	// 事件处理，一旦有事件触发了，就调用这个函数，来执行各个回调函数
	void HandlerEvent()
	{
		// EPOLLIN(普通可读事件) EPOLLRDHUP(对端半关闭或关闭连接) EPOLLPRI(紧急数据可读,优先数据)
		// EPOLLOUT (写事件) EPOLLERR (错误事件) EPOLLHUP (挂断事件)
		if ((_revent & EPOLLIN) || (_revent & EPOLLRDHUP) || (_revent & EPOLLPRI))
		{
			if (_read_callback)
			{
				DEL_LOG("触发可读事件,描述符：%d", _fd);
				_read_callback();
			}
		}
		if ((_revent & EPOLLOUT))
		{
			if (_write_callback)
			{
				DEL_LOG("触发写事件,描述符：%d", _fd);
				_write_callback();
			}
		}
		else if ((_revent & EPOLLERR))
		{
			if (_error_callback)
			{
				DEL_LOG("触发异常事件,描述符：%d", _fd);
			}
		}
		else if ((_revent & EPOLLHUP))
		{
			if (_close_callback)
			{
				DEL_LOG("触发链接关闭事件,描述符：%d", _fd);
				_close_callback();
			}
		}
		// 可以直接放到最后，不用担心因为释放连接了还要进行操作而造成崩溃，因为释放操作放到了任务队列中
		if (_event_callback)
		{
			DEL_LOG("触发任意事件,描述符：%d", _fd);
			_event_callback();
		}
	}
	// 设置可读事件回调
	void SetReadCallback(const EventCallback &cb)
	{
		_read_callback = cb;
	}
	// 设置可写事件回调
	void SetWriteCallback(const EventCallback &cb)
	{
		_write_callback = cb;
	}
	// 设置错误事件回调
	void SetErrorCallback(const EventCallback &cb)
	{
		_error_callback = cb;
	}
	// 设置挂断事件回调
	void SetCloseCallback(const EventCallback &cb)
	{
		_close_callback = cb;
	}
	// 设置任意事件回调
	void SetEventCallback(const EventCallback &cb)
	{
		_event_callback = cb;
	}
	EventLoop *Loop()
	{
		return _loop;
	}

private:
	EventLoop *_loop;
	int _fd;
	uint32_t _event;			   // 当前需要监控的事件
	uint32_t _revent;			   // 当前链接触发的事件
	EventCallback _read_callback;  // 可读事件回调
	EventCallback _write_callback; // 可写事件回调
	EventCallback _error_callback; // 错误事件回调
	EventCallback _close_callback; // 挂断事件回调
	EventCallback _event_callback; // 任意事件回调
};
